home *** CD-ROM | disk | FTP | other *** search
- head 1.7;
- branch ;
- access ;
- symbols ;
- locks ; strict;
- comment @ * @;
-
-
- 1.7
- date 89.07.31.17.42.10; author douglis; state Exp;
- branches ;
- next 1.6;
-
- 1.6
- date 89.06.15.22.45.35; author douglis; state Exp;
- branches ;
- next 1.5;
-
- 1.5
- date 89.01.21.16.33.30; author douglis; state Exp;
- branches ;
- next 1.4;
-
- 1.4
- date 89.01.13.11.42.01; author douglis; state Exp;
- branches ;
- next 1.3;
-
- 1.3
- date 89.01.05.11.57.07; author douglis; state Exp;
- branches ;
- next 1.2;
-
- 1.2
- date 89.01.04.21.03.00; author douglis; state Exp;
- branches ;
- next 1.1;
-
- 1.1
- date 88.09.21.14.07.31; author douglis; state Exp;
- branches ;
- next ;
-
-
- desc
- @Procedure to lock a file descriptor, optionally polling or breaking
- the lock.
- @
-
-
- 1.7
- log
- @reinstated code to break lock on behalf of other process
- @
- text
- @/*
- * DbLockDesc.c --
- *
- * Source code for the DbLockDesc procedure.
- *
- * Copyright 1988 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /sprite/src/lib/c/db/RCS/DbLockDesc.c,v 1.6 89/06/15 22:45:35 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- #endif not lint
-
-
- #include <db.h>
- #include "dbInt.h"
- #include <sys/signal.h>
- #include <sys/time.h>
- #include <stdio.h>
-
- #ifndef CLEAN
- int db_Contention = 0;
- #endif /* CLEAN */
-
- /*
- * Set the default timeout, in seconds.
- */
- #ifndef DB_LOCK_TIMEOUT
- #define DB_LOCK_TIMEOUT 10
- #endif /* DB_LOCK_TIMEOUT */
-
- /*
- *----------------------------------------------------------------------
- *
- * AlarmHandler --
- *
- * Routine to service a SIGALRM signal. This routine disables
- * the alarm (letting the caller reenable it when appropriate).
- *
- * Results:
- * None.
- *
- * Side effects:
- * The alarm is disabled.
- *
- *----------------------------------------------------------------------
- */
- static int
- AlarmHandler()
- {
-
- alarm(0);
- #ifdef DEBUG
- syslog(LOG_INFO, "Database lock timed out.");
- #endif /* DEBUG */
- (void) signal (SIGALRM, SIG_IGN);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * DbLockDesc --
- *
- * Lock a file descriptor, polling if necessary, and potentially
- * breaking the lock if timeout occurs.
- *
- * Results:
- * If the file is locked, by hook or by crook,
- * 0 is returned. If the file is not successfully locked,
- * -1 indicates an error and errno gives a more specific error.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- int
- DbLockDesc(handlePtr)
- Db_Handle *handlePtr;
- {
- int streamID; /* file descriptor */
- int type; /* type of lock */
- Db_LockHow action; /* DB_LOCK_{POLL,BLOCK,NO_BLOCK,WAIT,NONE} */
- int status;
- struct itimerval itimer, oldItimer;
- int (*oldHandler) ();
- int error;
- static int syslogDone = 0;
-
-
- streamID = handlePtr->streamID;
- action = handlePtr->lockHow;
- type = handlePtr->lockType;
-
- if (action == DB_LOCK_NONE) {
- return(0);
- }
- if (action != DB_LOCK_WAIT) {
- type |= LOCK_NB;
- }
- /*
- * Try the lock, then set a timer and try again.
- *
- * If the lock call times out in the RPC, return SUCCESS to keep the caller
- * from aborting.
- */
-
- status = flock(streamID, type);
- if (status == -1) {
- /*
- * It is possible to get a sprite RPC_TIMEOUT condition, or other
- * obscure error, which will map to EINVAL by default. We're mostly
- * interested in the EWOULDBLOCK condition, so if we get something
- * we know is likely to be innocuous, return 0. In particular,
- * we don't want our caller to abort because the lock timed out, since
- * it can wait for recovery.
- */
- if (errno == EINVAL) {
- return(0);
- }
- if ((errno != EWOULDBLOCK) || (action == DB_LOCK_NO_BLOCK)) {
- return(-1);
- }
- } else {
- return(0);
- }
-
- /*
- * Now lock in blocking mode, with an interval timer around to wake
- * us up if need be.
- */
- #ifndef CLEAN
- db_Contention++;
- #endif
-
- type &= ~LOCK_NB;
- itimer.it_interval.tv_sec = 0;
- itimer.it_interval.tv_usec = 0;
- itimer.it_value.tv_sec = DB_LOCK_TIMEOUT;
- itimer.it_value.tv_usec = 0;
-
- oldHandler = (int (*)()) signal(SIGALRM, AlarmHandler);
- if (oldHandler == (int (*)()) -1) {
- syslog(LOG_ERR, "Error setting signal handler.");
- return(-1);
- }
- if (setitimer(ITIMER_REAL, &itimer, &oldItimer) == -1) {
- error = errno;
- (void) signal(SIGALRM, oldHandler);
- errno = error;
- return(-1);
- }
- #ifdef LOCK_DEBUG
- syslog(LOG_INFO, "Debug msg: DB doing blocking lock with timeout.");
- #endif
-
- status = flock(streamID, type);
-
- #ifdef LOCK_DEBUG
- syslog(LOG_INFO, "Debug msg: blocking lock with timeout returned %d, errno %d.", status, errno);
- #endif
-
- error = errno;
- if (setitimer(ITIMER_REAL, &oldItimer, (struct itimerval *) NULL) == -1) {
- return(-1);
- }
- (void) signal(SIGALRM, oldHandler);
- if (status == -1) {
- errno = error;
- if (errno == EINVAL || errno == 0) {
- return(0);
- }
- if (errno != EINTR) {
- return(status);
- }
- if (action == DB_LOCK_POLL) {
- errno = ETIMEDOUT;
- return(-1);
- }
- #ifndef CLEAN
- if (!syslogDone) {
- syslog(LOG_INFO, "DbLockDesc: lock timed out (file %s).\n",
- handlePtr->fileName);
- syslogDone = 1;
- }
- #endif /* CLEAN */
-
- /*
- * Break the lock if required. Try to break an exclusive lock. If
- * that fails, and we were trying to get an exclusive lock, then try
- * releasing a shared lock since that could have been the problem.
- * Then try to get the lock again.
- * Return EWOULDBLOCK if breaking the lock wasn't successful.
- *
- * This has been commented out because one may no longer break
- * locks on behalf of other processes.
- */
- if (action == DB_LOCK_BREAK) {
- status = flock(streamID, LOCK_EX | LOCK_NB | LOCK_UN);
- if ((status != 0) && (type & LOCK_EX)) {
- (void) flock(streamID, LOCK_SH | LOCK_NB | LOCK_UN);
- }
- }
- status = flock(streamID, type | LOCK_NB);
- if (status == 0) {
- return(0);
- } else if (errno != EWOULDBLOCK) {
- return(status);
- } else {
- #ifdef CLEAN
- syslog(LOG_WARNING, "DbLockDesc: unable to lock stream %d in %s mode",
- streamID, (type & LOCK_EX) ? "exclusive" : "shared");
- #else /* CLEAN */
- syslog(LOG_WARNING, "DbLockDesc: unable to lock file %s in %s mode",
- handlePtr->fileName,
- (type & LOCK_EX) ? "exclusive" : "shared");
- #endif /* CLEAN */
- }
-
- /*
- * Once this thing is really production quality, it should return an error
- * if the lock times out. For now, especially as long as processes can go
- * into the debugger with a lock held, just return success anyway. We
- * tried.
- */
-
- #ifdef INSTALLED
- errno = EWOULDBLOCK;
- return (-1);
- #else /* INSTALLED */
- return(0);
- #endif /* INSTALLED */
- }
- return(0);
- }
-
-
- @
-
-
- 1.6
- log
- @only print syslog message once
- @
- text
- @d17 1
- a17 1
- static char rcsid[] = "$Header: /sprite/src/lib/c/db/RCS/DbLockDesc.c,v 1.5 89/01/21 16:33:30 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- a195 1
- #ifdef notdef
- a225 2
- errno = EWOULDBLOCK;
- return (-1);
- a226 1
- #endif /* notdef */
- @
-
-
- 1.5
- log
- @changed order of resetting signal handler and resetting
- interval timer to remove race condition.
- @
- text
- @d17 1
- a17 1
- static char rcsid[] = "$Header: /sprite/src/lib/c/db/RCS/DbLockDesc.c,v 1.4 89/01/13 11:42:01 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- d57 5
- d151 4
- d161 4
- d166 5
- d178 1
- a178 1
- if (errno = EINVAL) {
- d192 1
- @
-
-
- 1.4
- log
- @changed to take just a handle, which popints to the relevant
- info. fixed bug with locking and then not returning immediately.
- @
- text
- @d17 1
- a17 1
- static char rcsid[] = "$Header: /sprite/src/lib/c/db/RCS/DbLockDesc.c,v 1.3 89/01/05 11:57:07 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- a153 1
- (void) signal(SIGALRM, oldHandler);
- d157 1
- @
-
-
- 1.3
- log
- @changed to do blocking lock w/ timeout.
- @
- text
- @d17 1
- a17 1
- static char rcsid[] = "$Header: /sprite/src/lib/c/db/RCS/DbLockDesc.c,v 1.1 88/09/21 14:07:31 douglis Exp Locker: douglis $ SPRITE (Berkeley)";
- a56 1
- syslog(LOG_INFO, "DbLockDesc: lock timed out.\n");
- d81 3
- a83 1
- DbLockDesc(streamID, type, action)
- a86 1
- {
- d91 1
- d94 4
- d170 8
- d184 3
- d200 1
- d202 6
- a207 1
- streamID, (type & LOCK_EX) ? "exclusive" : "shared");
- d211 15
- d229 2
- @
-
-
- 1.2
- log
- @fixed what looked like a bug that would cause contention to wait for a
- long time rather than returning the first time the lock succeeded.
- @
- text
- @d23 3
- d27 10
- d41 24
- a86 1
- int delay;
- d88 3
- a90 4
- int numTries; /* Counter through the loop polling the lock */
- int numRetries; /* Counter through a loop retrying in the
- * event we break the lock and someone else
- * grabs it. */
- d92 1
- d100 1
- a100 2
- * Try the lock, then loop. This gets rid of an extraneous delay
- * after the last unsuccessful lock try.
- d102 1
- a102 1
- * If the lock call times out, return SUCCESS to keep the caller
- d126 31
- a156 16
- for (numRetries = 0; numRetries < NUM_TRIES; numRetries++) {
- delay = DELAY;
- for (numTries = 0; numTries < NUM_TRIES; numTries++) {
- (void) sleep(delay);
- delay *= 2;
- status = flock(streamID, type);
- if (status == -1) {
- if (errno = EINVAL) {
- return(0);
- }
- if ((errno != EWOULDBLOCK) || (action == DB_LOCK_NO_BLOCK)) {
- return(status);
- }
- } else {
- return(0);
- }
- d158 3
- d162 2
- a163 1
- return(ETIMEDOUT);
- d178 1
- a178 1
- status = flock(streamID, type);
- d183 5
- d190 1
- a190 4
- syslog(LOG_WARNING, "DbLockDesc: unable to lock stream %d in %s mode",
- streamID, (type & LOCK_EX) ? "exclusive" : "shared");
- errno = EWOULDBLOCK;
- return (-1);
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @d17 1
- a17 1
- static char rcsid[] = "$Header: DbLockDesc.c,v 1.2 88/09/13 16:48:36 douglis Exp $ SPRITE (Berkeley)";
- d104 2
- @
-